package com.app;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public abstract class AnnFieldPopulator<E, T extends Annotation>{
	
	private Class<T> annClass;
	
	public AnnFieldPopulator(Class<T> annClass){
		this.annClass = annClass;
	}
	
	public void populateInstance(Object instance){
		
		populate(instance.getClass(), instance);
	}
	
	public void populateClass(Class<?> aClass){
		
		populate(aClass, null);
	}
	
	private void populate(Class<?> aClass, Object instance){
		
		Field[] fields = aClass.getDeclaredFields();
		
		for(Field field : fields){
			if(field.isAnnotationPresent(annClass)){

				E value = newFieldValue(field, field.getAnnotation(annClass));
				trySetFieldValue(field, instance, value);
			}
		}
	}
	
	protected abstract E newFieldValue(Field field, T annotation);	
	
	private void trySetFieldValue(Field field, Object instance, Object value){
		try {
			setFieldValue(field, instance, value);
		} catch (Exception e) {
			throw new IllegalStateException("Couldnt set field value", e);
		}
	}
	
	private void setFieldValue(Field field, Object instance, Object value) throws IllegalArgumentException, IllegalAccessException{
		field.setAccessible(true);
		field.set(instance, value);
	}
}
